package com.ly.activiti.service.impl;

import com.github.pagehelper.Page;
import com.ly.activiti.domain.ActWorkflowFormData;
import com.ly.activiti.domain.dto.ActTaskDTO;
import com.ly.activiti.domain.dto.ActWorkflowFormDataDTO;
import com.ly.activiti.service.IActTaskService;
import com.ly.activiti.service.IActWorkflowFormDataService;
import com.ly.common.core.page.PageDomain;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.FormProperty;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class ActTaskServiceImpl implements IActTaskService {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private TaskRuntime taskRuntime;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private IActWorkflowFormDataService iActWorkflowFormDataService;


    @Override
    public Page<ActTaskDTO> selectProcessDefinitionList (PageDomain pageDomain) {
        Page<ActTaskDTO> list = new Page<ActTaskDTO> ();
        org.activiti.api.runtime.shared.query.Page<Task> pageTasks = taskRuntime.tasks ( Pageable.of ( ( pageDomain.getPageNum () - 1 ) * pageDomain.getPageSize(), pageDomain.getPageSize() ) );
        List<Task> tasks = pageTasks.getContent ();
        int totalItems = pageTasks.getTotalItems ();
        list.setTotal ( totalItems );
        if ( totalItems != 0 ) {
            Set<String> processInstanceIdIds = tasks.parallelStream ().map ( t -> t.getProcessInstanceId () ).collect ( Collectors.toSet () );
            List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery ().processInstanceIds ( processInstanceIdIds ).list ();
            List<ActTaskDTO> actTaskDTOS = tasks.stream ()
                    .map ( t -> new ActTaskDTO ( t, processInstanceList.parallelStream ().filter ( pi -> t.getProcessInstanceId ().equals ( pi.getId () ) ).findAny ().get () ) )
                    .collect ( Collectors.toList () );
            list.addAll ( actTaskDTOS );

        }
        return list;
    }

    @Override
    public List<String> formDataShow (String taskID) {
        Task task = taskRuntime.task ( taskID );
/*  ------------------------------------------------------------------------------
            FormProperty_0ueitp2--__!!类型--__!!名称--__!!是否参数--__!!默认值
            例子：
            FormProperty_0lovri0--__!!string--__!!姓名--__!!f--__!!同意!!__--驳回
            FormProperty_1iu6onu--__!!int--__!!年龄--__!!s

            默认值：无、字符常量、FormProperty_开头定义过的控件ID
            是否参数：f为不是参数，s是字符，t是时间(不需要int，因为这里int等价于string)
            注：类型是可以获取到的，但是为了统一配置原则，都配置到
            */

        //注意!!!!!!!!:表单Key必须要任务编号一模一样，因为参数需要任务key，但是无法获取，只能获取表单key“task.getFormKey()”当做任务key
        UserTask userTask = (UserTask) repositoryService.getBpmnModel ( task.getProcessDefinitionId () )
                .getFlowElement ( task.getFormKey () );

        if ( userTask == null ) {
            return null;
        }
        List<FormProperty> formProperties = userTask.getFormProperties ();
        List<String> collect = formProperties.stream ().map ( fp -> fp.getId () ).collect ( Collectors.toList () );

        return collect;
    }

    @Override
    public int formDataSave (String taskID, List<ActWorkflowFormDataDTO> awfs) throws ParseException {
        Task task = taskRuntime.task ( taskID );
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery ().processInstanceId ( task.getProcessInstanceId () ).singleResult ();

        Boolean hasVariables = false;//没有任何参数
        HashMap<String, Object> variables = new HashMap<String, Object> ();
        //前端传来的字符串，拆分成每个控件
        List<ActWorkflowFormData> acwfds = new ArrayList<> ();
        for ( ActWorkflowFormDataDTO awf : awfs ) {
            ActWorkflowFormData actWorkflowFormData = new ActWorkflowFormData ( processInstance.getBusinessKey (), awf, task );
            acwfds.add ( actWorkflowFormData );
            //构建参数集合
            if ( ! "f".equals ( awf.getControlIsParam () ) ) {
                variables.put ( awf.getControlId (), awf.getControlValue () );
                hasVariables = true;
            }
        }//for结束
        if ( task.getAssignee () == null ) {
            taskRuntime.claim ( TaskPayloadBuilder.claim ().withTaskId ( task.getId () ).build () );
        }
        if ( hasVariables ) {
            //带参数完成任务
            taskRuntime.complete ( TaskPayloadBuilder.complete ().withTaskId ( taskID )
                                           .withVariables ( variables )
                                           .build () );
        } else {
            taskRuntime.complete ( TaskPayloadBuilder.complete ().withTaskId ( taskID )
                                           .build () );
        }


        //写入数据库
        return iActWorkflowFormDataService.insertActWorkflowFormDatas ( acwfds );
    }
}
